package net.lb.socketserver.bus;

import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import net.lb.baseutil.collection.ByteBufferPool;
import net.lb.baseutil.collection.ByteCache;
import net.lb.baseutil.collection.ByteCachePool;
import net.lb.socketserver.handler.MessageHandler;
import net.lb.socketserver.util.HeadFactory;

public class Message
{
    private ByteCache         businessData;
    private ServerChannelInfo channelInfo;
    private byte              command;
    private byte              result;
    private MessageHandler    handler;
    private ByteBuffer        writeBuffer;
    private Boolean           writed        = Boolean.FALSE;
    private volatile byte     requestResult = BusinessCommand.REQUEST_SUCCESS;
    private volatile boolean  flowFinish    = false;
    private HeadFactory       headFactory;
    
    public Message(HeadFactory headFactory)
    {
        this.headFactory = headFactory;
    }
    
    public ByteCache getBusinessData()
    {
        return businessData;
    }
    
    public void setBusinessData(ByteCache businessData)
    {
        this.businessData = businessData;
    }
    
    public ServerChannelInfo getChannelInfo()
    {
        return channelInfo;
    }
    
    public void setChannelInfo(ServerChannelInfo channelInfo)
    {
        this.channelInfo = channelInfo;
    }
    
    public byte getCommand()
    {
        return command;
    }
    
    public void setCommand(byte command)
    {
        this.command = command;
    }
    
    public byte getResult()
    {
        return result;
    }
    
    public void setResult(boolean success)
    {
        if (success)
        {
            result = BusinessCommand.REQUEST_SUCCESS;
        }
        else
        {
            result = BusinessCommand.REQUEST_FAIL;
        }
    }
    
    public void setHandler(MessageHandler messageHandler)
    {
        this.handler = messageHandler;
    }
    
    public MessageHandler getHandler()
    {
        return handler;
    }
    
    public ByteBuffer getWriteBuffer()
    {
        return writeBuffer;
    }
    
    public void tryWrite()
    {
        if (flowFinish == false || writed)
        {
            return;
        }
        Queue<Message> sendQueue = channelInfo.getSendQueue();
        if (sendQueue.peek() == this)
        {
            synchronized (writed)
            {
                if (writed == false)
                {
                    writed = true;
                }
                else
                {
                    return;
                }
            }
            writeBuffer = ByteBufferPool.getBuffer(businessData.getCount() + 8);
            headFactory.putHeadInBuffer(writeBuffer, command, businessData.getCount());
            writeBuffer.put(command).put(requestResult);
            writeBuffer.putInt(businessData.getCount());
            writeBuffer.put(businessData.getDirectArray(), 0, businessData.getCount());
            writeBuffer.flip();
            channelInfo.getSocketChannel().write(writeBuffer, 10, TimeUnit.SECONDS, this, channelInfo.getMessageWriteCompleteHandler());
            ByteCachePool.returnCache(businessData);
        }
    }
    
    /**
     * 当前流程已经完成
     */
    public void flowFinish()
    {
        flowFinish = true;
    }
    
    public void requestFail()
    {
        requestResult = BusinessCommand.REQUEST_FAIL;
    }
}
